﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OpenComposite.Base;
using System.Windows.Forms;

namespace OC.Designer.Designer
{
	public class Helper
	{
		/// <summary>
		/// Creates a drag'n'drop cursor from a tree node.
		/// </summary>
		/// <param name="contextControl">The context control.</param>
		/// <param name="effect">The effect.</param>
		/// <param name="node">The tree node.</param>
		/// <returns>A <see cref="T:OpenComposite.Base.BitmapCursor"/>.</returns>
		public static BitmapCursor CreateDragCursorFromTreeNode(
			Control contextControl, DragDropEffects effect, TreeNode node)
		{
			Cursor cursor;
			switch ( effect ) {
				case DragDropEffects.None: cursor = Cursors.No; break;
				default: cursor = Cursors.Default; break;
			}
			int width = node.Bounds.Width;
			int height = node.Bounds.Height;
			if ( node.TreeView != null && node.TreeView.ImageList != null ) {
				width += node.TreeView.ImageList.ImageSize.Width;
			}
			Rectangle r = new Rectangle(0, 0, width + 1, height + 1);

			using ( Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb) )
			using ( Graphics g = Graphics.FromImage(bmp) ) {
				System.Drawing.Text.TextRenderingHint originalTextRenderingHint = g.TextRenderingHint;
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
				g.Clear(Color.FromArgb(0, 255, 255, 255));

				Color cb1 = Color.FromArgb(32, 255, 255, 255);
				Color cb2 = Color.FromArgb(0, 255, 255, 255);
				using ( Brush b = new System.Drawing.Drawing2D.LinearGradientBrush(r, cb1, cb2, 0, false) )
					g.FillRectangle(b, 0, 0, width, height);

				float textxpos = 0.0f;
				if ( node.TreeView != null && node.TreeView.ImageList != null ) {
					if ( node.ImageIndex >= 0 ) {
						g.DrawImage(node.TreeView.ImageList.Images[node.ImageIndex], 0, 0);
						textxpos = node.TreeView.ImageList.ImageSize.Width;
					} else if ( !string.IsNullOrEmpty(node.ImageKey) ) {
						g.DrawImage(node.TreeView.ImageList.Images[node.ImageKey], 0, 0);
						textxpos = node.TreeView.ImageList.ImageSize.Width;
					} else {
						g.DrawImage(node.TreeView.ImageList.Images[0], 0, 0);
						textxpos = node.TreeView.ImageList.ImageSize.Width;
					}
				}

				Color ct1 = Color.FromArgb(196, SystemColors.ControlText);
				using ( Brush b = new System.Drawing.SolidBrush(ct1) ) {
					g.DrawString(node.Text, contextControl.Font, b, textxpos, 0);
				}
				g.TextRenderingHint = originalTextRenderingHint;
				return new BitmapCursor(cursor, bmp, effect);
			}
		}
		/// <summary>
		/// Creates a drag'n'drop cursor.
		/// </summary>
		/// <param name="image">The image.</param>
		/// <param name="text">The text.</param>
		/// <param name="font">The font.</param>
		/// <param name="effect">The drag'n'drop effect.</param>
		/// <returns>A <see cref="T:OpenComposite.Base.BitmapCursor"/>.</returns>
		public static BitmapCursor CreateDragCursor(
			Image image, string text, Font font, DragDropEffects effect)
		{
			// select base cursor
			Cursor cursor;
			switch ( effect ) {
				case DragDropEffects.None: cursor = Cursors.No; break;
				default: cursor = Cursors.Default; break;
			}
			int width = 1;
			int height = 1;
			// create helper bitmap and graphics for string measuring
			using ( Bitmap bmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb) )
			using ( Graphics g = Graphics.FromImage(bmp) ) {
				// disable text antialiasing
				System.Drawing.Text.TextRenderingHint originalTextRenderingHint = g.TextRenderingHint;
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
				// calculate info image size (image + text)
				SizeF sizef = g.MeasureString(text, font);
				width = (int)Math.Ceiling(sizef.Width) + 1;
				height = (int)Math.Ceiling(sizef.Height) + 1;
				if ( image != null ) {
					width += image.Width + 1;
					if ( height < image.Height ) height = image.Height;
				}
				g.TextRenderingHint = originalTextRenderingHint;
			}
			// create bitmap and graphics
			using ( Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb) )
			using ( Graphics g = Graphics.FromImage(bmp) ) {
				// disable text antialiasing
				System.Drawing.Text.TextRenderingHint originalTextRenderingHint = g.TextRenderingHint;
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
				// clear graphic
				g.Clear(Color.FromArgb(0, 255, 255, 255));
				Rectangle rect = new Rectangle(0, 0, width, height);
				// fill text background with a linear gradient
				Color cb1 = Color.FromArgb(32, 255, 255, 255);
				Color cb2 = Color.FromArgb(0, 255, 255, 255);
				using ( Brush b = new System.Drawing.Drawing2D.LinearGradientBrush(rect, cb1, cb2, 0, false) ) {
					g.FillRectangle(b, 0, 0, width, height);
				}
				// text x position
				float textxpos = 0.0f;
				// draw image
				if ( image != null ) {
					g.DrawImage(image, 0, 0);
					textxpos = image.Width + 1;
				}
				// draw text
				Color ct1 = Color.FromArgb(196, SystemColors.ControlText);
				using ( Brush b = new System.Drawing.SolidBrush(ct1) ) {
					g.DrawString(text, font, b, textxpos, 0);
				}
				g.TextRenderingHint = originalTextRenderingHint;
				// create BitmapCursor
				return new BitmapCursor(cursor, bmp, effect);
			}
		}
		/// <summary>
		/// Creates a drag'n'drop cursor.
		/// </summary>
		/// <param name="cursor">The cursor.</param>
		/// <param name="image">The drag item image.</param>
		/// <param name="text">The drag item text.</param>
		/// <param name="font">The drag item text font.</param>
		/// <returns>A <see cref="T:OpenComposite.Base.BitmapCursor"/>.</returns>
		public static BitmapCursor CreateDragCursor(
			Cursor cursor, Image image, string text, Font font)
		{
			int width = 1;
			int height = 1;
			// create helper bitmap and graphics for string measuring
			using ( Bitmap bmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb) )
			using ( Graphics g = Graphics.FromImage(bmp) ) {
				// disable text antialiasing
				System.Drawing.Text.TextRenderingHint originalTextRenderingHint = g.TextRenderingHint;
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
				// calculate info image size (image + text)
				SizeF sizef = g.MeasureString(text, font);
				width = (int)Math.Ceiling(sizef.Width) + 1;
				height = (int)Math.Ceiling(sizef.Height) + 1;
				if ( image != null ) {
					width += image.Width + 1;
					if ( height < image.Height ) height = image.Height;
				}
				g.TextRenderingHint = originalTextRenderingHint;
			}
			// create bitmap and graphics
			using ( Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb) )
			using ( Graphics g = Graphics.FromImage(bmp) ) {
				// disable text antialiasing
				System.Drawing.Text.TextRenderingHint originalTextRenderingHint = g.TextRenderingHint;
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
				// clear graphic
				g.Clear(Color.FromArgb(0, 255, 255, 255));
				Rectangle rect = new Rectangle(0, 0, width, height);
				// fill text background with a linear gradient
				Color cb1 = Color.FromArgb(32, 255, 255, 255);
				Color cb2 = Color.FromArgb(0, 255, 255, 255);
				using ( Brush b = new System.Drawing.Drawing2D.LinearGradientBrush(rect, cb1, cb2, 0, false) ) {
					g.FillRectangle(b, 0, 0, width, height);
				}
				// text x position
				float textxpos = 0.0f;
				// draw image
				if ( image != null ) {
					g.DrawImage(image, 0, 0);
					textxpos = image.Width + 1;
				}
				// draw text
				Color ct1 = Color.FromArgb(196, SystemColors.ControlText);
				using ( Brush b = new System.Drawing.SolidBrush(ct1) ) {
					g.DrawString(text, font, b, textxpos, 0);
				}
				g.TextRenderingHint = originalTextRenderingHint;
				// create BitmapCursor
				return new BitmapCursor(cursor, bmp);
			}
		}
	}
}
